import React, { useRef } from 'react';
import styles from './index.less';
import { useDrag, useDrop } from 'react-dnd';
import { CARD } from '../itemType';

// useDrag 对应的项目拖动源， DragSource useDrop对应的项目叫放置目标 DropTarget
const Card = ({ id, text, index, moveCard }: any) => {
  // { current: null } 生成真实DMO后,会把DOM赋给ref.current
  const refs: any = useRef();

  const [, drop] = useDrop({
    // 一个字符串，这个放置目标会对指定类型的拖动源发送反应
    accept: CARD,
    // 鼠标按住拖动的时候
    hover(item: any, monitor) {
      // 获取被拖动的卡片索引
      const dragIndex = item.index;
      // 当前正在hover卡片索引
      const hoverIndex = index;
      console.log(item);
      console.log(monitor);

      if (dragIndex === hoverIndex) {
        return;
      }

      const { top, bottom } = refs.current.getBoundingClientRect();
      const halfOfHverHeight = (bottom - top) / 2;
      const { y }: any = monitor.getClientOffset();
      const hoverClientY = y - top;
      if (
        (dragIndex < hoverIndex && hoverClientY > halfOfHverHeight) ||
        (dragIndex > hoverIndex && hoverClientY < halfOfHverHeight)
      ) {
        moveCard(dragIndex, hoverIndex);
        item.index = hoverIndex;
      }
    },
  });

  // useDrag hook提供一种将组件作为拖拽连接 到 React Dnd系统中的方法
  // DragSource Ref 拖动源的连接器，连接 你的真实DOM和你的React Dnd系统
  let [{ isDragging }, drag] = useDrag({
    type: CARD,
    // 必需的是一个函数或者说对象，它是一个用于描述拖动源的普通JS对象
    item: () => ({ id, index }),
    // 收集功能，用来收集属性的，返回一个js对象，并且返回值会合并到你的组件属性中
    // monitor 里面存放的是一些拖动的状态，当拖动状态发送变化时，通知组件重新获取 属性并进行刷新组件
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  // 透明的
  const opacity = isDragging ? 0.1 : 1;

  // 拖动
  drag(refs);
  // 拖放的地方
  drop(refs);

  return (
    <div ref={refs} className={styles.box} style={{ opacity }}>
      {text}
    </div>
  );
};

export default Card;
